package org.example.AQS;

import java.util.concurrent.locks.Condition;

public class 自定义AQS {

    private static int count = 0;


    public static void main(String[] args) {
        testMyLock();
    }

    public static void testMyLock(){
        MyLock myLock = new MyLock();
        /**
         * Condition接口提供了类似Object(wait()/notify())的监视器方法，与Lock配合可以实现等待/通知模式,一个Condition的实例必须与一个Lock绑定，因此Condition一般都是作为Lock的内部实现
         */
        Condition condition = myLock.newCondition();
        new Thread(() -> {
            myLock.lock();
            try {
                System.out.println("进入等待!");
                /**
                 * 当调用await()方法后，当前线程会释放锁并在此等待而,其他线程调用Condition对象的signal()方法，通知当前线程后，当前线程才从await()方法返回，并且在返回前已经获取了锁。
                 * 造成当前线程在接到信号或被中断之前一直处于等待状态
                 */
                condition.await(); // 释放锁
                System.out.println("接收到通知！继续执行！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 100; i++) {
                count += 1;
                System.out.println(Thread.currentThread().getName() + ", count = " + count);
            }
            myLock.unlock();

        }).start();

        new Thread(() -> {
            myLock.lock();
            try {
                System.out.println("进入等待!");
                /**
                 * 当调用await()方法后，当前线程会释放锁并在此等待而,其他线程调用Condition对象的signal()方法，通知当前线程后，当前线程才从await()方法返回，并且在返回前已经获取了锁。
                 * 造成当前线程在接到信号或被中断之前一直处于等待状态
                 */
                condition.await(); // 释放锁
                System.out.println("接收到通知！继续执行！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 100; i++) {
                count += 1;
                System.out.println(Thread.currentThread().getName() + ", count = " + count);
            }
            myLock.unlock();

        }).start();

        new Thread(() -> {
            try {
                System.out.println("模拟3秒后发送通知过！");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myLock.lock();
            for (int i = 0; i < 100; i++) {
                count += 1;
                System.out.println(Thread.currentThread().getName() + ", count = " + count);
            }
            /**
             * 唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
             * 将会唤醒在等待队列中等待最长时间的节点（条件队列里的首节点）(类似于公平锁)
             */
            condition.signal();
            //signalAll唤醒所有等待线程
            //condition.signalAll();
            myLock.unlock();
        }).start();
    }

}
